local app = require "app"
local game = require "club.threecard.sudoku"
local Color = CS.UnityEngine.Color
local Vector3 = CS.UnityEngine.Vector3
local Vector2 = CS.UnityEngine.Vector2
local Ease = CS.DG.Tweening.Ease

local NormalColor = Color(1, 1, 1, 1)
local ErrorColor = Color(0.988, 0.137, 0.137, 1)
local HouseHighlightColor = Color(0.945, 0.925, 0.863, 1)

local M = game.ui.element()

local STYLE_MAP = {
    [4] = {
        column_count = 2,
        cell_size = Vector2(72, 72),
        font_size = 48
    },
    [6] = {
        column_count = 3,
        cell_size = Vector2(48, 48),
        font_size = 36
    },
    [9] = {
        column_count = 3,
        cell_size = Vector2(32, 32),
        font_size = 32
    },
}

local function get_number_text(value)
    if not value or value < 0 then
        return ""
    end
    return tostring(value)
end

function M:ctor(board, x, y, value)
    self.res = "club.threecard.sudoku/ui/ingame.b:cell" .. tostring(board.size)
    self.board = board
    self.x = x
    self.y = y
    self.value = value
    self.candidates = {}
end

function M:on_injected(bind)
    bind("trigger.down", self.trigger, self.on_trigger_down)
    bind("trigger.enter", self.trigger, self.on_trigger_enter)
    
    local style = STYLE_MAP[self.board.size]
    self.text.text = get_number_text(self.value)
    self.grid.constraintCount = style.column_count
    self.grid.cellSize = style.cell_size

    self.candidates[1] = self.n1
    self.candidates[2] = self.n2
    self.candidates[3] = self.n3
    self.candidates[4] = self.n4
    self.candidates[5] = self.n5
    self.candidates[6] = self.n6
    self.candidates[7] = self.n7
    self.candidates[8] = self.n8
    self.candidates[9] = self.n9
    
    for n, candidate_text in ipairs(self.candidates) do
        candidate_text.gameObject:SetActive(n <= self.board.size)
        candidate_text.enabled = false
        candidate_text.fontSize = style.font_size
    end
end

function M:update_color(state)
    self.selected_obj:SetActive(not not state.selected)
    if state.error then
        self.bg_image.color = ErrorColor
    elseif state.house_highlight then
        self.bg_image.color = HouseHighlightColor
    else
        self.bg_image.color = NormalColor
    end
end

function M:update_candidates(state)
    for n, candidate_text in ipairs(self.candidates) do
        candidate_text.enabled = not not state.candidates[n]
    end
end

function M:force_wrong_color()
    self.selected_obj:SetActive(false)
    self.bg_image.color = ErrorColor
end

function M:set_position(x, y)
    self.x = x
    self.y = y
end

function M:set_value(value)
    self.value = value
    self.text.text = get_number_text(value)
end

function M:hide_value()
    self.text.enabled = false
end

function M:hide_candidates()
    for n, candidate_text in ipairs(self.candidates) do
        candidate_text.enabled = false
    end
end

function M:show_value()
    self.text.enabled = true
    self.text.transform.localScale = Vector3.zero
    self.text.transform:DOScale(Vector3.one, 0.3):SetEase(Ease.InOutCirc)
end

function M:on_trigger_down(e)
    self.board:on_cell_click(self)
end

function M:on_trigger_enter(e)
    if e.pointerPress then
        self.board:on_cell_click(self)
    end
end

return M